﻿//This C# code file was released under the Ms-PL license
//http://www.opensource.org/licenses/ms-pl.html
//This script was originally intended for use with Microsoft Dynamics AX
//and maintained and distributed as a project on CodePlex
//http://dynamicsaxbuild.codeplex.com

using System;
using System.Collections.Generic;
using System.Text;
using System.Activities;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Build.Workflow.Activities;
using System.IO;
using System.Xml;

namespace AXTFSBuildLibrary
{
    [BuildActivity(HostEnvironmentOption.All)]
    public class XppCompileOutput : CodeActivity
    {
        [RequiredArgument]
        public InArgument<string> LogPath { get; set; }

        public InArgument<bool> ShowTODOs { get; set; }
        public InArgument<bool> ShowWarnings { get; set; }
        public InArgument<bool> ShowErrors { get; set; }
        public InArgument<bool> ShowBestPractices { get; set; }
        public InArgument<bool> FailBuildOnError { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            bool failBuildOnError = FailBuildOnError.Get(context);
            bool hasErrors = false;
            bool showTODOs = ShowTODOs.Get(context);
            bool showWarnings = ShowWarnings.Get(context);
            bool showErrors = ShowErrors.Get(context);
            bool showBestPractices = ShowBestPractices.Get(context);
            string filePath = LogPath.Get(context) + @"\AxCompileAll.html";

            XmlDocument doc = GetXML(filePath);

            XmlNodeList nodes;
            System.Collections.IEnumerator nodeEnumerator;

            XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
            nsmgr.AddNamespace("Table", "urn:www.microsoft.com/Formats/Table");
            nodes = doc.SelectNodes("//Table:Record", nsmgr);
            if (nodes != null)
            {
                nodeEnumerator = nodes.GetEnumerator();
                while (nodeEnumerator.MoveNext())
                {
                    XmlNode node = nodeEnumerator.Current as XmlNode;

                    string treeNodePath = node.SelectSingleNode("Table:Field[@name='TreeNodePath']", nsmgr).InnerText;
                    string line = node.SelectSingleNode("Table:Field[@name='Line']", nsmgr).InnerText;
                    string column = node.SelectSingleNode("Table:Field[@name='Column']", nsmgr).InnerText;
                    string severity = node.SelectSingleNode("Table:Field[@name='SysCompilerSeverity']", nsmgr).InnerText;
                    string message = node.SelectSingleNode("Table:Field[@name='SysCompileErrorMessage']", nsmgr).InnerText;

                    string output = String.Format("{0}, line {1}, column {2} : {3}", treeNodePath, line, column, message);

                    switch (severity)
                    {
                        case "0":
                            if (showErrors)
                                context.TrackBuildError(output);
                            hasErrors = true;
                            break;
                        case "1":
                        case "2":
                        case "3":
                            if (showWarnings)
                                context.TrackBuildWarning(output);
                            break;
                        case "4":
                            if (showBestPractices)
                                context.TrackBuildMessage(output);
                            break;
                        case "254":
                        case "255":
                            if (showTODOs)
                                context.TrackBuildMessage(output);
                            break;
                    }
                }

                if (failBuildOnError && hasErrors)
                    throw new Exception("X++ Compile Error(s)");
            }
        }

        protected XmlDocument GetXML(string filename)
        {
            string xml = "";

            bool xmlBlock = false;
            using (StreamReader streamReader = new StreamReader(File.OpenRead(filename)))
            {
                while (!streamReader.EndOfStream)
                {
                    string line = streamReader.ReadLine().Trim();

                    if (line == "<AxaptaCompilerOutput>")
                        xmlBlock = true;

                    if (!xmlBlock)
                        continue;

                    xml = String.Format("{0}{1}{2}", xml, line, System.Environment.NewLine);

                    if (line == "</AxaptaCompilerOutput>")
                        xmlBlock = false;
                }
            }

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            return doc;
        }
    }
}
